<script setup>
import { ref, shallowRef, onBeforeUnmount, watch } from 'vue'
import '@wangeditor/editor/dist/css/style.css'
import { Editor, Toolbar } from '@wangeditor/editor-for-vue'
import { generalFileUpload } from '@/api/upload'
import logger from '@/utils/logger'
import { ElMessage } from 'element-plus'

// 定义组件属性
const props = defineProps({
  modelValue: {
    type: String,
    default: '',
  },
  placeholder: {
    type: String,
    default: '请输入内容...',
  },
  height: {
    type: [String, Number],
    default: 300,
  },
  disabled: {
    type: Boolean,
    default: false,
  },
})

// 定义组件事件
const emit = defineEmits(['update:modelValue', 'change'])

// 编辑器实例，必须用 shallowRef
const editorRef = shallowRef()

// 编辑器内容
const IMAGE_STYLE =
  'display:block;width:100%;max-width:100%;height:auto;margin:12px auto;object-fit:contain;'

const normalizeImageStyle = (html) => {
  if (!html) return ''
  if (typeof window === 'undefined') return html
  const container = document.createElement('div')
  container.innerHTML = html
  const images = container.querySelectorAll('img')
  images.forEach((img) => {
    img.setAttribute('style', IMAGE_STYLE)
  })
  return container.innerHTML
}

const valueHtml = ref(normalizeImageStyle(props.modelValue))

// 工具栏配置
const toolbarConfig = {
  excludeKeys: ['fullScreen', 'emotion', 'group-video'], // 移除全屏按钮、表情按钮和视频相关按钮
}
// 编辑器配置
const editorConfig = {
  placeholder: props.placeholder,
  readOnly: props.disabled,
  scroll: false,
  MENU_CONF: {
    uploadImage: {
      // 自定义上传图片
      async customUpload(file, insertFn) {
        try {
          const res = await generalFileUpload(file)
          if (res && res.code === 200 && res.data) {
            // 成功后插入图片 URL
            insertFn(res.data, file.name)
          } else {
            ElMessage.error('富文本图片上传失败')
          }
        } catch (error) {
          logger.error('富文本图片上传失败', error)
          ElMessage.error('富文本图片上传失败')
        }
      },
    },
  },
}

// 监听内容变化
const handleChange = (editor) => {
  const normalized = normalizeImageStyle(editor.getHtml())
  valueHtml.value = normalized
  emit('update:modelValue', valueHtml.value)
  emit('change', valueHtml.value)
}

// 监听外部传入的值变化
watch(
  () => props.modelValue,
  (newVal) => {
    if (newVal !== valueHtml.value) {
      valueHtml.value = normalizeImageStyle(newVal)
    }
  },
)

// 组件销毁时，销毁编辑器
onBeforeUnmount(() => {
  const editor = editorRef.value
  if (editor == null) return
  editor.destroy()
})
</script>

<template>
  <div class="rich-text-editor">
    <Toolbar
      :editor="editorRef"
      :defaultConfig="toolbarConfig"
      :mode="disabled ? 'simple' : 'default'"
      style="border-bottom: 1px solid #ccc"
    />
    <Editor
      v-model="valueHtml"
      :defaultConfig="editorConfig"
      :mode="disabled ? 'simple' : 'default'"
      style="flex: 1; overflow-y: auto"
      @onChange="handleChange"
      @onCreated="editorRef = $event"
    />
  </div>
</template>

<style scoped>
.rich-text-editor {
  width: 100%;
  height: calc(100vh - 200px);
  display: flex;
  flex-direction: column;
}
:deep(.w-e-text-container) {
  /* 富文本编辑器内容区域样式 */
  h1 {
    font-size: 2em;
    font-weight: bold;
    margin-top: 0.67em;
    margin-bottom: 0.67em;
  }
  h2 {
    font-size: 1.5em;
    font-weight: bold;
    margin-top: 0.83em;
    margin-bottom: 0.83em;
  }
  h3 {
    font-size: 1.17em;
    font-weight: bold;
    margin-top: 1em;
    margin-bottom: 1em;
  }
  h4 {
    font-size: 1em;
    font-weight: bold;
    margin-top: 1.33em;
    margin-bottom: 1.33em;
  }
  h5 {
    font-size: 0.83em;
    font-weight: bold;
    margin-top: 1.67em;
    margin-bottom: 1.67em;
  }
  h6 {
    font-size: 0.67em;
    font-weight: bold;
    margin-top: 2.33em;
    margin-bottom: 2.33em;
  }
  p {
    margin-top: 1em;
    margin-bottom: 1em;
  }
  ul,
  ol {
    padding-left: 2em;
    margin-top: 1em;
    margin-bottom: 1em;
  }
  ul {
    list-style-type: disc;
  }
  ol {
    list-style-type: decimal;
  }
  li {
    display: list-item;
  }
  blockquote {
    margin: 1em 40px;
    padding-left: 1em;
    border-left: 4px solid #ccc;
  }
}
</style>
